using System;
using System.Collections.Generic;
using System.Text;
using Barrage;
using Spacedash.Logic;
using Barrage.Items;
using Spacedash.Game.Scenes;
using SlimDX;
using Barrage.Render.Passes;
using Barrage.Scenes;
using Barrage.Global;
using Barrage.Render;
using SlimDX.Direct3D9;

namespace Spacedash.Game.Subgames
{
    class RaceSection:GameSection
    {
        public override int Id
        {
            get { return (int)GameState.Playing; }
        }
        
        protected Race race;
        public Race Race { get { return race; } }

        protected List<Postprocess> blurProcesses = new List<Postprocess>(4);

        protected List<RaceHUDScene> raceHUDScenes=new List<RaceHUDScene>(4);
        protected RaceScene raceScene;

        public RaceSection(Race race, SpacedashGame parent)
            : base(parent)
        {
            this.race = race;
            SetViewportSize();
        }

        public override void MainLoop()
        {
            race.Update();
            UpdateBlur();
            if (Keyboard.Instance.KeyReleased(SlimDX.DirectInput.Key.Escape)||Gamepad.AnyButtonReleased(SlimDX.XInput.GamepadButtonFlags.Back))
                parent.NextGameSectionId = (int)GameState.MainMenu;
            if (race.State.State == RaceStateList.Finished)
                parent.NextGameSection = new RaceResumeSection(race,(SpacedashGame) parent);
        }

        protected void UpdateBlur()
        {
            for (int i = 0; i < race.Ships.Count; i++)
            {
                float previousBlur = blurProcesses[i].Mesh.FirstMaterial.FloatParameters[0];
                blurProcesses[i].Mesh.FirstMaterial.FloatParameters[0] = (float)GameMath.Damping(previousBlur,(float)Math.Pow(Math.Max(0,Math.Min(10,race.Ships[i].Speed-3)),1.15f) / 130.0f,0.025f,Timer.DefaultTimer.LastIntervalSeconds);
                Quaternion q = raceScene.Cameras[i].Motion.Rotation;

                Vector4 v = Vector3.Transform(race.Ships[i].Motion.ZVector, q);
                v = Vector4.Transform(v, raceScene.Cameras[i].Projection);
                
                if (v.W < 0) v.X = -v.X;
                else v.Y = -v.Y;
                v = GameMath.UnprojectVector(v);
                v.Normalize();
                v += new Vector4(0.5f, 0.5f, 0, 0);
                blurProcesses[i].Mesh.FirstMaterial.Vector4Parameters[0] = v;
            }
            
        }
        Vector2 viewportSize;

        void SetViewportSize()
        {
            switch (race.PlayerNumber)
            {
                default:
                case 1:
                    viewportSize = new Vector2(Engine.DefaultRenderTargetDescription.Width, Engine.DefaultRenderTargetDescription.Height);
                    break;
                case 2:
                    viewportSize = new Vector2(Engine.DefaultRenderTargetDescription.Width, Engine.DefaultRenderTargetDescription.Height / 2);
                    break;
                case 3:
                    viewportSize = new Vector2(Engine.DefaultRenderTargetDescription.Width, Engine.DefaultRenderTargetDescription.Height / 3);
                    break;
                case 4:
                    viewportSize = new Vector2(Engine.DefaultRenderTargetDescription.Width / 2, Engine.DefaultRenderTargetDescription.Height / 2);
                    break;
            }
            
        }
            
        protected override void initRenderProcesses()
        {
            
            for (int i = 0; i < race.PlayerNumber; i++)
            {
                Viewport viewport = new Viewport();
                switch (race.PlayerNumber)
                {
                    case 1:
                    case 4:
                        viewport.X = (i % 2) * (int)viewportSize.X;
                        viewport.Y = (i / 2) * (int)viewportSize.Y;
                        break;
                    case 3:
                    case 2:
                        viewport.X = 0;
                        viewport.Y = i * (int)viewportSize.Y;
                        break;
                }
                viewport.MaxZ = 1;
                viewport.MinZ = 0;
                viewport.Width = (int)viewportSize.X;
                viewport.Height = (int)viewportSize.Y;

                RenderPass scenePass;
                if (Engine.Config[GameConfig.ANTIALIAS].Equals("true"))
                    scenePass = new AntialiasRenderPass(new Vector2(viewport.Width, viewport.Height));
                else
                    scenePass = new RenderPass(new Vector2(viewport.Width, viewport.Height));
                scenePass.MustClear = true;
                scenePass.BackgroundColor = new Color4(1, 0.8f, 0.8f, 0.8f);
                scenePass.addSource(raceScene, raceScene.Cameras[i]);

                // Second pass: Postprocess the antialiased scene with a radial blur
                PostprocessScene ppScene = new PostprocessScene();
                Postprocess blurProcess = new Postprocess(scenePass.RenderTarget, "RadialBlur.fx");
                blurProcess.Material.FloatParameters.Add(0);
                blurProcess.Material.Vector4Parameters.Add(new Vector4(0.5f, 0.7f, 0, 0));
                ppScene.Add(blurProcess);
                blurProcesses.Add(blurProcess);

                RenderProcess renderProcess = new RenderProcess((Texture)null);
                renderProcess.Viewport = viewport;
                renderProcess.FinalRenderPass.MustClear = false;
                renderProcess.FinalRenderPass.DepthBuffer = null;
                renderProcess.FinalRenderPass.ZCull = false;

                renderProcess.addIntermediatePass(scenePass);
                // The result of the blur postprocess can be rendered directly to backbuffer
                renderProcess.addSource(ppScene);
                // After the blur process draw the HUD
                renderProcess.addSource(raceHUDScenes[i]);

                AddRenderProcess(renderProcess);
            }
        }

        protected override void initScenes()
        {
            raceScene = new RaceScene(race,viewportSize);
            AddScene(raceScene);
            foreach (Ship s in race.Ships)
            {
                RaceHUDScene raceHUDScene = new RaceHUDScene(race, s);
                raceHUDScenes.Add(raceHUDScene);
                AddScene(raceHUDScene);
            }
        }

        public override void Dispose()
        {
            race = null;
            raceHUDScenes.Clear();
            raceScene = null;
            blurProcesses.Clear();
            base.Dispose();
        }
    }
}
